# ======================================================================
#
# Copyright (C) ADN
# ADN::LIBRARY::SNMP::Gestion Gestion.pm
# Description:
#  - Gestion des connexions SNMP 
#
# ======================================================================

package ADN::LIBRARY::SNMP::Gestion;

use strict;
use ADN::LIBRARY::IP::Ip;
use ADN::LIBRARY::SNMP::Snmp;
use ADN::LIBRARY::SNMP::Snmpv1;
use Net::SNMP qw(:snmp);
use ADN::CONF::Read;

# #######################
# CREAT OBJECT SELF + INIT. VAR.
# #######################
sub new
{
	  my $self = shift;
	  my $class = ref($self) || $self;
	  return $self if ref $self;
	  $self = bless {} => $class;
	  ($self->{BASE_OID}, $self->{ref_SYSTEM}) = @_;
    $self->{auto_erreur} = 0;
    $self->{session} = 0;
    if ($self->_init() =~ m/^[-]1$/smx)
    {
      return -1;
    }
    return $self;
}

# #######################
# INIT.
# #######################
sub _init
{
	my $self = shift;
  my $conf = ADN::CONF::Read->new();
  if ($conf =~ m/^[-]1$/smx)
  {
    return -1;
  }
  my %SNMP = $conf->SNMP();
  foreach my $keys (keys(%SNMP))
  {
    $self->{$keys} = $SNMP{$keys};
  }
	undef $conf;
	return;
}

# #######################
# MAIN
# #######################
sub start
{
  my $self = shift;
  ($self->{HOST}) = @_;
  my %erreur;

  $self->{session} = 0;
  $self->boucle_compte();
  if ($self->{session} =~ m/^0$/smx)
  {
    $erreur{auth} = -1;
    return %erreur;
  }
  else
  {
    return $self->requete();
  }
  return;
}

# #######################
# REQUEST V1 OR V2/3
# #######################
sub requete
{
  my $self = shift;
  my ($ref, $session);

  if ($self->{version} =~ m/^1$/smx)
  {
    $session = ADN::LIBRARY::SNMP::Snmpv1->new($self->{ref_SYSTEM});
    $ref = $session->start($self->{session});
  }
  elsif ($self->{version} =~ m/^2$|^3$/smx)
  {
    $session = ADN::LIBRARY::SNMP::Snmp->new($self->{BASE_OID}, $self->{ref_SYSTEM});
    $ref = $session->start($self->{session});
  }
  undef $session;
  return %{$ref};
}

# #######################
# CREDETIALS
# #######################
sub boucle_compte
{
  my $self = shift;
  my $cnt = 0;

  while ($self->{compte} != $cnt)
  {
    if ($self->{session} =~ m/^0$/smx)
    {
      $self->{version} = $self->{'version'.$cnt};
      $self->{community} = $self->{'community'.$cnt};
      $self->{port} = $self->{'port'.$cnt};
      $self->{username} = $self->{'username'.$cnt};
      $self->{authkey} = $self->{'authkey'.$cnt};
      $self->{authpasswd} = $self->{'authpasswd'.$cnt};
      $self->{authproto} = $self->{'authproto'.$cnt};
      $self->{privkey} = $self->{'privkey'.$cnt};
      $self->{privpasswd} = $self->{'privpasswd'.$cnt};
      $self->{privproto} = $self->{'privproto'.$cnt};
      $self->{ip_auth} = $self->{'ip_auth'.$cnt};
      if ($self->ctr_ip())
      {
        $self->distribution();
      }
    }
    $cnt++;
  }
  undef $cnt;
  return;
}

# #######################
# RIGHT, IP
# #######################
sub ctr_ip
{
  my $self = shift;
  my (@tab_ip, @IPs);
  my ($ip_tab, $ip, $liste_ip);

  if ($self->{ip_auth} =~ m/^$/smx)
  {
    return 1;
  }
  @tab_ip = split /;/smx, $self->{ip_auth};
  foreach $ip_tab (@tab_ip)
  {
    if ($ip_tab =~ m/^0$/smx)
    {
      return 0;
    }
    $liste_ip = ADN::LIBRARY::IP::Ip->new($ip_tab);
    @IPs = $liste_ip->start();
    foreach $ip (@IPs)
    {
      if ($ip =~ m/^($self->{HOST})$/smx)
      {
        return 1;
      }
    }
  }
  return 0;
}

# #######################
# AUTO OR V1 OR V2 OR V3
# #######################
sub distribution
{
  my $self = shift;

  if ($self->{version} =~ m/^auto$/smx)
  {
    $self->auto();
  }
  elsif ($self->{version} =~ m/^1$/smx)
  {
    $self->noAuthNoPrivv1();
  }
  elsif ($self->{version} =~ m/^2$/smx)
  {
    $self->noAuthNoPriv();
  }
  elsif ($self->{version} =~ m/^3$/smx)
  {
    $self->authPriv();
    if (($self->{version} =~ m/^3$/smx) and ($self->{session} !~ m/^0$/smx))
    {
      $self->authNoPriv();
      if (($self->{version} =~ m/^3$/smx) and ($self->{session} !~ m/^0$/smx))
      {
        $self->noAuthNoPrivV3();
      }
    }
  }
  return
}

# #######################
# SNMP V2
# #######################
sub noAuthNoPriv
{
  my $self = shift;

  my ($session, $error) = Net::SNMP->session(
	           -version     => $self->{version},
	           -nonblocking => 1,
	           -hostname    => shift || $self->{HOST},
	           -community   => shift || $self->{community},
	           -port        => shift || $self->{port},
	           -timeout	    => $self->{timeout} );

  if (defined $session)
  {
    $self->{session} = $session;
    $self->{auto_erreur} = -1;
  }
  return;
}

# #######################
# SNMP V1
# #######################
sub noAuthNoPrivv1
{
  my $self = shift;

  my ($session, $error) = Net::SNMP->session(
	           -version     => $self->{version},
	           -hostname    => shift || $self->{HOST},
	           -community   => shift || $self->{community},
	           -port        => shift || $self->{port},
	           -timeout	    => $self->{timeout});
  if (defined $session)
  {
    $self->{session} = $session;
    $self->{auto_erreur} = -1;
  }
  return;
}

# #######################
# SNMP V3 (Simple)
# #######################
sub noAuthNoPrivV3
{
  my $self = shift;

  my ($session, $error) = Net::SNMP->session(
	           -version     => '3',
	           -nonblocking => 1,
	           -hostname    => shift || $self->{HOST},
	           -username    => shift || $self->{username},
	           -port        => shift || $self->{port},
	           -timeout	    => $self->{timeout} );
  if (defined $session)
  {
    $self->{session} = $session;
    $self->{auto_erreur} = -1;
  }
  return;
}

# #######################
# SNMP V3 (Authentification)
# #######################
sub authNoPriv
{
  my $self = shift;

  my ($session, $error) = Net::SNMP->session(
	           -version       => '3',
	           -nonblocking   => 1,
	           -hostname      => shift || $self->{HOST},
             -authkey       => shift || $self->{authkey},
             -authpassword  => shift || $self->{authpasswd}, # 1 octect
             -authprotocol  => shift || $self->{authproto}, # md5 ou sha
	           -port          => shift || $self->{port},
	           -timeout	      => $self->{timeout} );
  if (defined $session)
  {
    $self->{session} = $session;
    $self->{auto_erreur} = -1;
  }
  else
  {
    $self->{auto_erreur} = 2;
  }
  return;
}

# #######################
# SNMP V3 (Athentification + Chiffrement)
# #######################
sub authPriv
{
  my $self = shift;

  my ($session, $error) = Net::SNMP->session(
	           -version       => '3',
	           -nonblocking   => 1,
	           -hostname      => shift || $self->{HOST},
             -authkey       => shift || $self->{authkey},
             -authpassword  => shift || $self->{authpasswd}, # 1 octect
             -authprotocol  => shift || $self->{authproto}, # md5 ou sha
             -privkey       => shift || $self->{privkey},
             -privpassword  => shift || $self->{privpasswd},
             -privprotocol  => shift || $self->{privproto},   # des ou aes ou aes128 ou 3des ou 3desede
	           -port          => shift || $self->{port},
	           -timeout	      => $self->{timeout} );
  if (defined $session)
  {
    $self->{session} = $session;
    $self->{auto_erreur} = -1;
  }
  else
  {
    $self->{auto_erreur} = 1;
  }
  return;
}

# #######################
# SNMP AUTO
# #######################
sub auto
{
  my $self = shift;

  if (($self->{auto_erreur} != -1) and ($self->{session} == 0))
  {
    if (($self->{authkey} !~ m/^$/smx) and ($self->{authpasswd} !~ m/^$/smx) and ($self->{authproto} !~ m/^$/smx) and ($self->{auto_erreur} < 3))
    {
      if (($self->{privkey} !~ m/^$/smx) and ($self->{privpasswd} !~ m/^$/smx) and ($self->{privproto} !~ m/^$/smx) and ($self->{auto_erreur} < 1))
      {
        $self->authPriv();
      }
      else
      {
        $self->authNoPriv();
      }
    }
    else
    {
      if (!($self->noAuthNoPrivV3()) and ($self->{community} !~ m/^$/smx))
      {
        $self->{version} = '2';
        $self->noAuthNoPriv();
        if ($self->{auto_erreur} != -1)
        {
          $self->{version} = '1';
          $self->noAuthNoPriv();
          if ($self->{auto_erreur} != -1)
          {
            return 0;
          }
        }
      }
    }
  }
  return;
}

# #######################
# DESTROY OBJECT
# #######################
sub DESTROY {
    my $self = shift;
    return;
}
1;
__END__